#define  _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/un.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <sys/timerfd.h>
#include <sys/sysinfo.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/reboot.h>
#include <stdbool.h>
#include <getopt.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>

#include "../utils/net.h"
#include "../utils/io.h"
#include "../utils/map.h"
#include "execute.h"
#include "unit.h"

typedef struct {   
    HashMap* unitMap;
    Transaction* transaction;
    int eventfd;
    int timerfd;
    int epoll_fd;
} SystemManager;

SystemManager manager;

/**
 * Initialize signal handling for the event loop
 * @param epoll_fd Epoll file descriptor
 * @return Signal file descriptor on success, -1 on failure
 */
static int initSignalHandling(int epoll_fd) {
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    sigaddset(&mask, SIGTERM);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGQUIT);
    sigaddset(&mask, SIGRTMIN+1); // undefined signal
    sigaddset(&mask, SIGRTMIN+2); // child process ready
    sigaddset(&mask, SIGUSR1);

    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
        errno = EPERM; // permission denied
        return -1;
    }

    int sfd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
    if (sfd < 0) {
        return -1;
    }

    epmsg_t *epmsg = epmsg_init(sfd, EPOLLET|EPOLLIN, NULL, NULL);
    if (epmsg_add(epoll_fd, epmsg) == -1) {
        close(sfd);
        return -1;
    }

    return sfd;
}

/**
 * Handle incoming socket connections
 * @param listener Listener socket file descriptor
 * @param evmsg Event message pointer
 * @return 1 if shutdown requested, 0 otherwise
 */
static int handleSocketConnection(int listener, epmsg_t *evmsg) {
    struct sockaddr_un client_addr;
    int clen = sizeof(client_addr);
    int client_socket = accept(listener, (struct sockaddr*)&client_addr, (socklen_t*)&clen);
    if (client_socket < 0) {
        return 0;
    }

    fdcloexec(client_socket);
    HTTP_REQUEST req={0};
    recv_http_request_v1(client_socket,&req,NULL);
    // ...解析http
    close(client_socket);
    return 0;
}

/**
 * Handle system signals
 * @param fdsi Signal info structure
 * @return 1 if shutdown requested, 0 otherwise
 */
static int handleSystemSignal(struct signalfd_siginfo *fdsi) {
    if (fdsi->ssi_signo == SIGCHLD) {
        sigcld_handler(fdsi);
    } 
    else if (fdsi->ssi_signo == SIGINT || fdsi->ssi_signo == SIGTERM || fdsi->ssi_signo == SIGQUIT) {
        unlink("monitor.sock_path");
        printf("[\033[3;32mmonitord\033[0m] Shutdown.\n");
        return 1;
    }
    return 0;
}

/**
 * 事件循环
 */
void syncLoop() {
    SystemManager manager={
        .unitMap=hashmap_create(1024, sizeof(char*), sizeof(Unit*), string_hash, string_compare, free, NULL),
        .transaction=setTransaction(NULL)
    };
    int epoll_fd __attribute((cleanup(close)))= epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd < 0) {
        return -errno;
    }

    // 初始化信号处理
    int sfd __attribute((cleanup(close)))= initSignalHandling(epoll_fd);
    if (sfd < 0) {
        return -errno;
    }

    // 初始化监听套接字
    unlink("");
    int listener __attribute((cleanup(close)))= listenFrom("", SOCK_STREAM, 50);
    if (listener < 0) {
        return -errno;
    }
    fdcloexec(listener);

    epmsg_t *epmsg = epmsg_init(listener, EPOLLET|EPOLLIN, NULL, NULL);
    if (epmsg_add(epoll_fd, epmsg) == -1) {
        return -errno;
    }
    manager.eventfd=eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);


    // 事件循环
    struct epoll_event evts[20];
    while (true) {
        int ret = epoll_wait(epoll_fd, evts, 20, -1);
        if (ret < 0) {
            if (errno == EINTR) continue;
            break;
        }

        for (int i = 0; i < ret; i++) {
            epmsg_t *evmsg = (epmsg_t*)evts[i].data.ptr;
            
            if ((evts[i].events & EPOLLIN) && evmsg->fd == listener) {
                if (handleSocketConnection(listener, evmsg) == 1) {
                    goto shutdown;
                }
            }
            else if ((evts[i].events & EPOLLIN) && evmsg->fd == sfd) {
                struct signalfd_siginfo fdsi;
                ssize_t s = read(evmsg->fd, &fdsi, sizeof(fdsi));
                if (s == sizeof(fdsi) && handleSystemSignal(&fdsi) == 1) {
                    goto shutdown;
                }
            }
            else if ((evts[i].events & EPOLLIN) && evmsg->fd == manager.eventfd) {
                // 事件通知处理
                uint64_t state;
                read(manager.eventfd, &state, sizeof(state));
                TransactionState transactionState=driveTranstion(manager.transaction);
                if (transactionState == TRANSACTION_COMPLETE)
                {
                    printf("[\033[3;32mmonitord\033[0m] Transaction complete.\n");
                    close(manager.eventfd);
                }
                else if (transactionState == TRANSACTION_START || transactionState == TRANSACTION_STOP || transactionState == TRANSACTION_RESTART || transactionState == TRANSACTION_RELOAD)
                {
                    write(manager.eventfd, &transactionState, sizeof(transactionState));
                }
                else if (transactionState == TRANSACTION_WAIT)
                {
                    
                }
                else if (transactionState == TRANSACTION_ERROR)
                {
                    printf("[\033[3;32mmonitord\033[0m] Transaction error.\n");
                    close(manager.eventfd);
                }
                
                
            }
            
        }
    }

shutdown:

}